/*
 * @Author: 无聊 7989314+Hwz1997@user.noreply.gitee.com
 * @Date: 2025-10-24 14:16:25
 * @LastEditors: 无聊 7989314+Hwz1997@user.noreply.gitee.com
 * @LastEditTime: 2025-10-28 16:27:23
 * @FilePath: \keep_motion_api\middleWares\audit-log.middleware.js
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
const { Log } = require('@/models/permission');
const adminCodeList = ['super_admin', 'goods_admin', 'sports_admin', 'community_admin'];

// 添加审计日志
const auditLogMiddleware = async (req, res, next) => {
    if (!req.user || !req.user.userId || !req.user.role || !adminCodeList.includes(req.user.role)) {
        return next();
    }
    const startTime = Date.now();
    const { method, originalUrl, ip, body, query } = req;
    const adminId = req.user.userId;

    // 对 send 进行拦截 获取响应数据
    const originalSend = res.send;
    let responseBody = null;
    res.send = function(data) {
      responseBody = data;
      originalSend.call(this, data);
    }

    // 记录日志
    res.once('finish', async () => {
      try{
        if (res.statusCode > 204 || method === 'GET') return;
        const logData = {
          admin_id: adminId,
          action: `${method} ${originalUrl}`,
          target: determineTarget(originalUrl),
          target_id: req.params.id,
          ip_address: ip,
          timestamp: new Date(),
          execution_time: Date.now() - startTime,
          request_data: filterSensitiveData({ body, query }, 'request'),
          response_data: filterSensitiveData(JSON.parse(responseBody), 'response'),
          response_status: res.statusCode,
          is_sensitive: determineSensitivity(originalUrl, method)
        };
        await Log.create(logData);
      } catch (error) {
        console.error('记录审计日志时出错:', error);
      }
    });
    next();
}

// 根据url 确定操作目标
function determineTarget(url) {
  // 简单的URL分析逻辑，可以根据项目路由规则扩展
  const urlParts = url.split('/').filter(Boolean);
  if (urlParts.length >= 4) return urlParts[3];
  return 'unknown';
}

//根据URL确定是否为敏感操作
function determineSensitivity(url, method) {
  const sensitiveRoute = [
    {
      path: '/sys/dict-types',
      method: ['POST', 'PUT', 'DELETE']
    },
    {
        path: '/sys/dict-types/import',
        method: ['POST']
    },
    {
        path: '/sys/dict-data',
        method: ['POST', 'PUT', 'PATCH']
    },
    {
        path: '/sys/dict-data/import',
        method: ['POST']
    },
    {
      path: '/permission/menu',
      method: ['POST', 'PUT', 'DELETE']
    },
    {
        path: '/permissions/bind',
        method: ['POST']
    },
    {
      path: '/permission/roles',
      method: ['POST', 'PUT', 'DELETE']
    },
    {
      path: '/permission/admins',
      method: ['POST', 'PUT']
    },
    {
      path: '/permission/audit',
      method: ['DELETE']
    },
  ];
  return sensitiveRoute.some(item => item.path === url && item.method.includes(method));
}

//过滤敏感数据（如密码等）
function filterSensitiveData(data, type) {
  if (!data || typeof data !== 'object') {
    return data;
  }
  
  const sensitiveFields = [
    {key: '_id', reg: /(.{4}).*(.{4})$/, replace: '$1****$2'},
    {key: 'password', reg: /.*/, replace: '******'},
    {key: 'pwd', reg: /.*/, replace: '******'},
    {key: 'phone', reg: /(\d{3})\d{4}(\d{4})/, replace: '$1****$2'},
    {key: 'card_number', reg: /(\d{4})\d+(\d{4})/, replace: '$1****$2'}
  ];
  // 使用深拷贝避免修改原始数据
  const filteredData = JSON.parse(JSON.stringify(data));
  // 递归处理深层嵌套的数据
  function processNestedData(obj) {
    if (!obj || typeof obj !== 'object') {
      return obj;
    }
    // 处理数组
    if (Array.isArray(obj)) {
      return obj.map(item => processNestedData(item));
    }
    
    // 处理对象
    const result = { ...obj };
    
    // 应用敏感字段替换规则
    sensitiveFields.forEach(field => {
      if (result[field.key] && typeof result[field.key] === 'string') {
        result[field.key] = result[field.key].replace(field.reg, field.replace);
      }
    });
    
    // 检查并处理所有以_id结尾的字段
    Object.keys(result).forEach(key => {
      if (key.endsWith('_id') && typeof result[key] === 'string') {
        result[key] = result[key].replace(/(.{4}).*(.{4})$/, '$1****$2');
      }
    });
    
    // 递归处理对象的每个属性
    Object.keys(result).forEach(key => {
      if (result[key] && typeof result[key] === 'object') {
        result[key] = processNestedData(result[key]);
      }
    });
    
    return result;
  }
  
  if(type === 'request'){
    // 处理请求数据，深度遍历所有嵌套层级
    return processNestedData(filteredData);
  }
  else if(type === 'response'){
    // 处理响应数据，先检查常规结构
    if(!filteredData.data) return filteredData;
    
    // 深度处理响应数据中的所有内容
    filteredData.data = processNestedData(filteredData.data);
  }
  
  return filteredData;
}

module.exports = auditLogMiddleware;